import coin.exchange.base.kr_rest.level_book as level_book_mdl
import coin.exchange.base.kr_rest.public_client_base as pubcb
import coin.exchange.korbit_v1.kr_rest.native_public_client as npubc

from coin.exchange.korbit_v1.kr_rest.product import KorbitProduct
from coin.proto.coin_market_query_pb2 import ProductTicker, ExchangeTicker


class KorbitFeedParser(object):
  @staticmethod
  def parse_native_ticker(update_msg: dict, product) -> ProductTicker:
    """ Sample ticker json data:
    {
      "timestamp": 1394590350000,
      "last": "663699",
      "bid": "660001",
      "ask": "663699",
      "low": "642000",
      "high": "663699",
      "volume": "52.50203662"
    }
    """
    return ProductTicker(high=float(update_msg['high']),
                         low=float(update_msg['low']),
                         last=float(update_msg['last']),
                         ask=float(update_msg['ask']),
                         bid=float(update_msg['bid']),
                         exchange_timestamp=int(float(update_msg['timestamp']) * 1e+6),
                         volume_24hr=float(update_msg['volume']),
                         native_symbol=product.native_symbol,
                         symbol=product.symbol)

  @staticmethod
  def parse_level_book(update_msg, product):
    """ Sample response. According to the Korbit API documentation, the third
    value in each item of the asks/bids list is deprecated, its values is
    always "1".
    {
      "timestamp" : 1386135077000,
      "bids" : [["1100000", "0.0103918", "1"], ["1000000", "0.01000000", "1"], ... ],
      "asks" : [["569000", "0.50000000", "1"], ["568500", "2.00000000", "1"], ... ]
    }
    """
    level_book = level_book_mdl.LevelBook(product)
    for elem in update_msg['asks']:
      level_elem = level_book_mdl.LevelElement(float(elem[0]), float(elem[1]), 0)
      level_book.add_ask(level_elem)
    for elem in update_msg['bids']:
      level_elem = level_book_mdl.LevelElement(float(elem[0]), float(elem[1]), 0)
      level_book.add_bid(level_elem)
    level_book.finalize()
    return level_book


class KorbitPublicClient(pubcb.PublicClientBase):
  def __init__(self):
    self.npubc = npubc.KorbitNativePublicClient()

  def query_ticker_impl(self, product):
    symbol = product.native_symbol
    update = self.npubc.get_detailed_ticker(symbol)
    update.msg = KorbitFeedParser.parse_native_ticker(update.msg, product)
    return update

  def query_exchange_ticker_impl(self):
    product_ticker_list = []
    update = self.npubc.get_all_detailed_ticker()
    for native_symbol, raw_ticker in update.msg.items():
      product = KorbitProduct.FromStrNativeProduct(native_symbol)
      product_ticker = KorbitFeedParser.parse_native_ticker(raw_ticker, product)
      product_ticker_list.append(product_ticker)
    update.msg = ExchangeTicker(each_ticker=product_ticker_list,
                                market_type='Spot',
                                exchange='Korbit')
    return update

  def query_level_book_impl(self, product):
    symbol = product.native_symbol
    update = self.npubc.get_orderbook(symbol)
    update.msg = KorbitFeedParser.parse_level_book(update.msg, product)
    return update


if __name__ == "__main__":
  client = KorbitPublicClient()
  print(client.query_exchange_ticker())
  print(client.query_level_book(KorbitProduct.FromStr("BTC-KRW")))
